/*

	contents of memory

	(nm,type)		(add,2)   (clr,1)
		nm add clr push,lda lds
		type  2 --- 2byte
		type  1 --- 1byte
	numeric
		0-255

	?-com(pc).
	?-tokio test2.
	?-com(aktokio).
	?-tokio test.

aklist		ackerman's source
aktokio		its memory image
aktrace			result
asm		prolog assembler for this simple computer
pc		tokio sorce of simple pipeline computer

*/

:- static([mem(_),pc,sp,op1,op2,a,c,memout,memd]).

ifet(fetch) :-
	*memout <= *mem(*pc) ,
	*pc <= *pc+1
   &&	*op1 := *memout  
   &&	if (*memout = stop ) then empty 
        else 
	    (_Nm,Ty) = *memout, {
	    if Ty = 2
		 then ifet(op2fetch)
		 else exec(first)}.

ifet(op2fetch):-
        *memout <= *mem(*pc) , *pc <= *pc+1
   &&	*op2 := *memout &&  exec(first).

exec(first):- (Op,_) = *op1, exec_first(Op)
   && (Op,_) = *op1, exec_first_0(Op).

    exec_first(add) :-	 *memd <= *mem(*op2).
    exec_first(adc) :-	 *memd <= *mem(*op2).
    exec_first(clr) :-	 *a <= 0.
    exec_first(com) :-	 *a <= -(*a).
    exec_first(push) :-	 *mem(*sp) <= *a.
    exec_first(pull) :-	 *sp <= *sp+1.
    exec_first(lda) :-	 *a <= *mem(*op2).
    exec_first(sta) :-	 *mem(*op2) <= *a.
    exec_first(lds) :-	 *sp <= *mem(*op2).
    exec_first(sts) :-	 *mem(*op2) <= *sp.
    exec_first(jmp) :-	 *pc <= *op2.
    exec_first(jsr) :-	 *mem(*sp) <= *pc.
    exec_first(rts) :-	 *sp <= *sp+1.
    exec_first(clc) :-	 *c <= 0.
    exec_first(sec) :-	 *c <= 1.
    exec_first(brc) :-	 if *c = 1 then *pc <= *op2 .

    isShort(clr):-true.  isShort(com):-true.  isShort(lda):-true.
    isShort(sta):-true.  isShort(lds):-true.  isShort(sts):-true.   
    isShort(jmp):-true.
    isShort(clc):-true.  isShort(sec):-true.  isShort(brc):-true.
    isLong(add):-true.   isLong(adc):-true.
    isSec2(pull):-true.  isSec2(push):-true. isSec2(jsr):-true. 
    isSec2(rts):-true.

    exec_first_0(Op) :- isShort(Op),
	    ifet(fetch). 
    exec_first_0(Op) :- isLong(Op),
	    (exec(second) && true), ifet(fetch).
    exec_first_0(Op) :- isSec2(Op),
	    exec(sec2).

exec(second):- 
	(Op,_) = *op1,
	exec_second(Op).

    exec_second(add) :- *a <= (*a + *memd) mod 256.
    exec_second(adc) :- X = *a + *memd + *c,
	    (if X>255 then *c <= 1, *a <= X mod 256 else *c <= 0).

exec(sec2):- 
	(Op,_) = *op1,
	exec_sec2(Op) && ifet(fetch).

    exec_sec2(pull)	:- *a <= *mem(*sp).
    exec_sec2(jsr)	:- *pc <= *op2, *sp <= *sp-1.
    exec_sec2(rts)	:- *pc <= *mem(*sp).
    exec_sec2(push)	:- *sp <= *sp-1.

init:-
      *pc := 0 , *sp := 255 ,
      *a := 0, *c := 0,
      *memd	 := 0,
      *memout	 := 0 , 
      *op1	 := (clr,1), 
      *op2 	 := 0.

test2 :- init,
      *mem(0)	 := (lda,2),
      *mem(1)	 := 100,
      *mem(100)	 := 23,
      *mem(2)	 := (add,2),
      *mem(3)	 := 101,
      *mem(101)	 := 32,
      *mem(4)	 := (sta,2),
      *mem(5)	 := 102,
      *mem(6)	 := stop &&
	ifet(fetch), #desp.

desp :-	X = (pc= *pc,  a= *a, sp= *sp, c= *c,
		memout= *memout, op1= *op1, op2= *op2, memd= *memd ), write(X).
/* */
